package com.ruoyi.export.service.impl;


import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.develop.invoice.utils.InvoiceUtils;
import com.ruoyi.export.service.IExportService;
import com.ruoyi.export.utils.JxlsDateUtils;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jodconverter.DocumentConverter;
import org.jodconverter.document.DefaultDocumentFormatRegistry;
import org.jxls.common.Context;
import org.jxls.expression.JexlExpressionEvaluator;
import org.jxls.transform.Transformer;
import org.jxls.transform.poi.PoiTransformer;
import org.jxls.util.JxlsHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;
import org.springframework.web.multipart.MultipartFile;

/**
 * 导出业务层处理
 *
 * @author darlin
 * @date 2022-03-17
 */
@Service
public class ExportServiceImpl implements IExportService {

    @Resource
    private DocumentConverter documentConverter;

    @Value(value = "${ruoyi.path}")
    public String basePath;

    @Value(value = "${ruoyi.templatePath}")
    public String templatePath;

    @Value(value = "${ruoyi.templateExport}")
    public String templateExport;

    @Value(value = "${ruoyi.templateImport}")
    public String templateImport;

    @Value(value = "${ruoyi.templateTmpl}")
    public String templateTmpl;

    @Value(value = "${ruoyi.uploadPath}")
    public String uploadPath;

    @Value("${spring.profiles.active}")
    public String active;

    protected boolean isIE(HttpServletRequest request) {
        return request.getHeader("USER-AGENT").toLowerCase().indexOf("msie") > 0 || request.getHeader("USER-AGENT").toLowerCase().indexOf("rv:11.0") > 0;
    }

    protected boolean isChrome(HttpServletRequest request) {
        return request.getHeader("USER-AGENT").toLowerCase().indexOf("Mozilla") > 0;
    }

    /**
     * 根据模板名称下载模板
     *
     * @param fileName
     * @param templateName
     * @param request
     * @param response
     */
    @Override
    public void downloadTemplate(String fileName, String templateName,
                                 HttpServletRequest request, HttpServletResponse response) {
//        response.setContentType("application/force-download");// 设置强制下载不打开
        response.setCharacterEncoding("gb2312");
        response.setContentType("application/OCTET-STREAM;charset=gb2312");
        response.setHeader("Access-Control-Expose-Headers", "fileName");

        InputStream in = null;
        try {
            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateTmpl + File.separator + templateName);

            if (this.isIE(request)) {// IE浏览器
                fileName = URLEncoder.encode(fileName, "UTF8");
            } else if (this.isChrome(request)) {// google,火狐浏览器
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
            }
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("fileName", fileName);

            Context context = PoiTransformer.createInitialContext();

            JxlsHelper jxlsHelper = JxlsHelper.getInstance();
            jxlsHelper.setDeleteTemplateSheet(true);

            Transformer transformer = jxlsHelper.createTransformer(in, response.getOutputStream());

            //添加自定义工具
            JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig()
                    .getExpressionEvaluator();
            Map<String, Object> funcs = new HashMap<String, Object>();
            funcs.put("dateUtil", new JxlsDateUtils());
            //evaluator.getJexlEngine().setFunctions(funcs);
            JexlBuilder jb = new JexlBuilder();
            jb.namespaces(funcs);
            JexlEngine je = jb.create();
            evaluator.setJexlEngine(je);
            jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e);
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 根据模板，生成Excel内容，写入到前台
     *
     * @param fileName
     * @param data
     * @param templateName
     * @param request
     * @param response
     */
    @Override
    public void baseXlsxExport(String fileName,
                               Map<String, Object> data,
                               String templateName,
                               HttpServletRequest request,
                               HttpServletResponse response) {

        response.setCharacterEncoding("gb2312");
        response.setContentType("application/OCTET-STREAM;charset=gb2312");
        response.setHeader("Access-Control-Expose-Headers", "fileName");

        InputStream in = null;
        try {
            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator + templateName);

            if (this.isIE(request)) {// IE浏览器
                fileName = URLEncoder.encode(fileName, "UTF8");
            } else if (this.isChrome(request)) {// google,火狐浏览器
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            } else {
                fileName = URLEncoder.encode(fileName, "UTF8");// 其他浏览器
            }
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setHeader("fileName", fileName);

            Context context = PoiTransformer.createInitialContext();

            JxlsHelper jxlsHelper = JxlsHelper.getInstance();
            jxlsHelper.setDeleteTemplateSheet(true);

            context.toMap().putAll(data);


            Transformer transformer = jxlsHelper.createTransformer(in, response.getOutputStream());

            //添加自定义工具
            /*JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig()
                    .getExpressionEvaluator();
            Map<String, Object> funcs = new HashMap<String, Object>();
            funcs.put("dateUtil", new JxlsDateUtils());
            //evaluator.getJexlEngine().setFunctions(funcs);
            JexlBuilder jb = new JexlBuilder();
            jb.namespaces(funcs);
            JexlEngine je = jb.create();
            evaluator.setJexlEngine(je);*/

            jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println(e);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println(e);
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * 根据模板，生成内容，写入到前台
     *
     * @param fileName
     * @param data
     * @param templateName
     * @param request
     * @param response
     */
    @Override
    public void baseDocxExport(String fileName, Map<String, Object> data, String templateName, HttpServletRequest request, HttpServletResponse response) throws Exception {
        Map<String, Object> params = new HashMap<>();
        response.setHeader("Access-Control-Expose-Headers", "fileName");

        InputStream in = null;
        try {
            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator + templateName);

            if (!this.isIE(request)) {
                fileName = URLEncoder.encode(fileName, "UTF8");
            } else {
                fileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity);
            IContext context = report.createContext();
            context.putMap(params);
            report.process(context, response.getOutputStream());

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }

    }

    /**
     * 根据模板，生成内容，并写入到Word文件
     *
     * @param name
     * @param data
     * @param templateName
     */
    @Override
    public void convertDocx(String name, Map<String, Object> data, String templateName) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        InputStream in = null;
        try {
            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator + templateName);
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(
                    in, TemplateEngineKind.Freemarker);
            IContext context = report.createContext();
            context.putMap(data);
            report.process(context, out);
            String filePath = basePath + File.separator + uploadPath + File.separator + name;

            File file = new File(filePath);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileOutputStream fos = new FileOutputStream(filePath);
            fos.write(out.toByteArray());
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }


    /**
     * 根据模板，生成内容，并写入到Word文件 并返回网络路径
     *
     * @param fileName
     * @param data
     * @param templateName
     */
    @Override
    public String convertDocxAndUpload(String fileName, Map<String, Object> data, String templateName) {

        ByteArrayOutputStream out = new ByteArrayOutputStream();

        InputStream in = null;
        try {
            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator +"inspectReport" + File.separator+ templateName);

            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(
                    in, TemplateEngineKind.Freemarker);
            IContext context = report.createContext();
            context.putMap(data);

            report.process(context, out);
            byte[] woldFile =  out.toByteArray();
            byte[] pdf = convertPdf(woldFile);
            String filePath = basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator +"inspectReport" + File.separator+  fileName.substring(0, fileName.lastIndexOf("."))+".pdf";

            File file = new File(filePath);
            if (!file.exists()) {
                try {
                    file.createNewFile();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            FileOutputStream fos = new FileOutputStream(filePath);
            fos.write(pdf);
            fos.flush();
            fos.close();
            // 上传文件路径
            String path = RuoYiConfig.getUploadPath();
            MultipartFile multipartFile = FileUploadUtils.getMulFileByPath(fileName.substring(0, fileName.lastIndexOf(".")),file.getAbsolutePath());
            // 上传并返回新文件名称
            // 判断是测试环境 还是正式环境
            String newFile = "";
            System.out.println(RuoYiConfig.getProfile());
            if (active.equals("test")) {
                newFile= FileUploadUtils.uploadTest(path, multipartFile);
            }else{
                newFile = FileUploadUtils.upload(path, multipartFile);
            }
            file.delete();
            return newFile;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }


    private byte[] convertPdf(byte[] bytes){
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            documentConverter.convert(new ByteArrayInputStream(bytes)).as(DefaultDocumentFormatRegistry.DOCX)
                    .to(out).as(DefaultDocumentFormatRegistry.PDF).execute();
        }catch (Exception ex){
            ex.printStackTrace();
        }
        return out.toByteArray();
    }


    /**
     * 根据模板，生成内容，并写入到Excel文件
     *
     * @param name
     * @param data
     * @param templateName
     * @return
     */
    @Override
    public String convertXlsx2File(String name, Map<String, Object> data, String templateName) {
        String targetPath = basePath + File.separator + templatePath +
                File.separator + templateExport + File.separator + DateUtils.parseDateToStr("yyyy-MM-dd", new Date()) + File.separator;
        String filePath = targetPath + name;
        File targetFile = new File(targetPath);
//        File file = new File(filePath + name);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
            /*try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }*/
        }
        InputStream in = null;
        try {
            FileOutputStream fos = new FileOutputStream(filePath);

            in = new FileInputStream(basePath + File.separator + templatePath
                    + File.separator + templateExport + File.separator + templateName);

            Context context = PoiTransformer.createInitialContext();
            JxlsHelper jxlsHelper = JxlsHelper.getInstance();
            jxlsHelper.setDeleteTemplateSheet(true);
            context.toMap().putAll(data);

            Transformer transformer = jxlsHelper.createTransformer(in, fos);

            //添加自定义工具
            JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig()
                    .getExpressionEvaluator();
            Map<String, Object> funcs = new HashMap<String, Object>();
            funcs.put("dateUtil", new JxlsDateUtils());
            JexlBuilder jb = new JexlBuilder();
            jb.namespaces(funcs);
            JexlEngine je = jb.create();
            evaluator.setJexlEngine(je);

            jxlsHelper.setUseFastFormulaProcessor(false).processTemplate(context, transformer);

            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return filePath;
    }

}
